home *** CD-ROM | disk | FTP | other *** search
- /* FASTLOAD.C
- ************************************************************************
- * *
- * PC Scheme/Geneva 4.00 Borland C code *
- * *
- * (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- * (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- * *
- *----------------------------------------------------------------------*
- * *
- * Fast-Load a Module from a Port *
- * *
- *----------------------------------------------------------------------*
- * *
- * Created by: John Jensen Date: 1985 *
- * Revision history: *
- * - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- * *
- * ``In nomine omnipotentii dei'' *
- ************************************************************************/
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <ctype.h>
- #include "scheme.h"
-
- #define skip_space() while(iswhitespace(sgetc()));
-
- /* data structures to control file access */
- #define NUM_FILES 8 /* the maximum nesting of "%fasl" operations */
- #define BUF_LENGTH 4096 /* buffer length for fasl files */
- #define READ_ACC 0 /* file access code for "read" */
-
- static char *buffer; /* character string buffer */
- static int chr = 0; /* the current character */
- static int file_no = -1; /* the current file number */
- static char *file_buffer[NUM_FILES]; /* character buffers */
- static int file_handle[NUM_FILES]; /* handles for open files */
- static char *file_pos[NUM_FILES]; /* current position in buffer */
- static int file_end[NUM_FILES]; /* end of buffer */
-
- static char *f_pos, *f_end;
-
- /************************************************************************/
- /* Read In a Fast Load Format Object Module */
- /************************************************************************/
- int fasl(REGPTR reg)
- {
- char lcl_buffer[256];
- unsigned codebytes;
- unsigned constants;
- unsigned disp;
- int i;
- int len;
- unsigned page;
- int retstat = 0;
- int type;
- unsigned long dummy;
-
- buffer = lcl_buffer;
- page = CORRPAGE(reg->page);
- disp = reg->disp;
- type = ptype[page];
-
- if (type == STRTYPE) {
- if (file_no >= NUM_FILES - 1) {
- sprintf( buffer, "FAST-LOAD nesting too deep. Maximum is %d", NUM_FILES );
- set_error(1, buffer, &nil_reg );
- reset_fasl();
- retstat = -1;
- goto return_eof;
- }
- len = get_word(page, disp + 1);
- if (len < 0)
- len = len + BLK_OVHD;
- else
- len = len - BLK_OVHD;
- get_str(buffer, page, disp);
- buffer[len] = '\0';
- file_no++;
- if ((i = zopen(&file_handle[file_no], buffer, READ_ACC, &dummy)) != 0) {
- i += IO_ERROR_START;
- alloc_string(&tmp_reg, buffer);
- dos_error(1, i, &tmp_reg);
- }
- if (!(file_pos[file_no] = (file_buffer[file_no] = (char *)
- malloc(BUF_LENGTH))))
- malloc_error("fasl");
- file_end[file_no] = 0;
- }
- f_pos = file_pos[file_no];
- f_end = file_buffer[file_no] + (file_end[file_no]);
-
- /* read and validate fasl program header; get # constants and codebytes */
- skip_space();
- while (chr == '#') {
- for (i = 0; i < 11; i++)
- if (sgetc() != "!fast-load "[i])
- goto invalid_fasl;
- while (sgetc() != '\n') /* do nothing */
- ;
- skip_space();
- }
- if (chr == EOF || chr == CTRL_Z)
- goto close_file;
- if (chr != 'h')
- goto invalid_fasl;
- constants = next_word();
- codebytes = next_word();
-
- /* allocate and zero the code block */
- alloc_block(reg, CODETYPE, constants * sizeof(POINTER) + sizeof(POINTER) + codebytes);
- page = CORRPAGE(reg->page);
- disp = reg->disp;
- zero_blk(page, disp);
- disp += BLK_OVHD;
-
- /* insert the entry point offset */
- put_ptr(page, disp, ADJPAGE(SPECFIX), constants * sizeof(POINTER) + sizeof(POINTER) + BLK_OVHD);
-
- /* process the constants list entries */
- disp = sizeof(POINTER) + BLK_OVHD;
- while (constants--) {
- if (read_constant())
- goto invalid_fasl;
- put_ptr(CORRPAGE(reg->page), reg->disp + disp, tmp_reg.page, tmp_reg.disp);
- disp += sizeof(POINTER);
- }
-
- /* validate the "text" portion header and read in bytecodes */
- skip_space();
- if (chr != 't')
- goto invalid_fasl;
- zap_chars(reg, disp, codebytes);
-
- /* validate the fasl module trailer */
- skip_space();
- if (chr == 'z') {
- file_pos[file_no] = f_pos;
- return retstat;
- }
- invalid_fasl:
- set_error(0, "Invalid FAST-LOAD module", &nil_reg);
- retstat = -1;
-
- close_file:
- zclose(file_handle[file_no]);
- free(file_buffer[file_no]);
- file_no--;
- return_eof:
- reg->page = ADJPAGE(EOF_PAGE);
- reg->disp = EOF_DISP;
-
- return retstat;
- }
-
- /************************************************************************/
- /* Read In a Constant Entry */
- /************************************************************************/
- int read_constant(void)
- {
- unsigned disp;
- int i;
- int len;
- unsigned lpage = 0; /* page number for a list cell */
- unsigned page;
-
- tail_recursion:
- skip_space();
- switch (chr) {
- case 'x': /* symbol */
- len = next_byte();
- for (i = 0; i < len; i++)
- buffer[i] = sgetc();
- intern(&tmp_reg, buffer, len);
- break;
-
- case 'i': /* short integer constant */
- tmp_reg.page = ADJPAGE(SPECFIX);
- tmp_reg.disp = next_word();
- break;
-
- case 'l': /* list cell */
- if (nextcell[listpage] != END_LIST) {
- tmp_reg.page = ADJPAGE(listpage);
- tmp_reg.disp = nextcell[listpage];
- nextcell[listpage] = get_word(listpage, tmp_reg.disp + 1);
- } else
- alloc_list_cell(&tmp_reg);
- toblock(&tmp_reg, 0, &nil_reg, sizeof(LIST));
- if (lpage) { /* we're building a linked list-- update previous cdr */
- c_pop(&tm2_reg);
- put_ptr((lpage = CORRPAGE(tm2_reg.page)), tm2_reg.disp + 3, tmp_reg.page, tmp_reg.disp);
- } else { /* starting a list-- preserve list header pointer */
- c_push(&tmp_reg);
- }
- c_push(&tmp_reg);/* record this list cell's location */
- checkstack();
- if(read_constant())
- return 1;
- put_ptr(lpage = CORRPAGE(s_stack[topofstack / sizeof(POINTER)].page),
- s_stack[topofstack / sizeof(POINTER)].disp, tmp_reg.page, tmp_reg.disp);
- goto tail_recursion;
-
- case 'n':
- tmp_reg = nil_reg;
- break;
-
- case 's': /* string constant */
- len = next_word();
- alloc_block(&tmp_reg, STRTYPE, len);
- zap_chars(&tmp_reg, 3, len);
- break;
-
- case 'c': /* character constant */
- tmp_reg.page = ADJPAGE(SPECCHAR);
- tmp_reg.disp = next_byte();
- break;
-
- case 'b': /* bignum constant */
- {
- SCHEMEOBJ o;
-
- len = next_byte();
- alloc_block(&tmp_reg, BIGTYPE, 2*len + 1);
- o = reg2c(&tmp_reg);
- o->bignum.data.sign = next_byte();
- for( int i = 0; i < len; i++ )
- o->bignum.data.data[i] = next_word();
- break;
- }
- case 'f': /* flonum constant */
- alloc_flonum(&tmp_reg, next_flonum());
- break;
-
- case 'v': /* vector */
- len = next_word();
- alloc_block( &tm2_reg, VECTTYPE, 3*len );
- zero_blk( CORRPAGE(tm2_reg.page), tm2_reg.disp );
- checkstack();
- for( i = 0; i < len; i++ )
- {
- SCHEMEOBJ o;
-
- c_push(&tm2_reg); /* save pointer to vector object */
- if(read_constant()) /* read next vector entry */
- return 1;
- c_pop(&tm2_reg); /* restore pointer to vector object */
-
- o = reg2c(&tm2_reg);
- o->vector.data[i].page = tmp_reg.page;
- o->vector.data[i].disp = tmp_reg.disp;
- }
- tmp_reg = tm2_reg;
- break;
-
- case 'm': /* machine language */
- {
- SCHEMEOBJ o;
-
- len = next_word();
- alloc_block( &tmp_reg, I86TYPE, len );
- o = reg2c(&tmp_reg);
-
- for( i = 0; i < len; i++ )
- o->i86block.data[i] = sgetc();
- break;
- }
-
- default:
- zprintf("read_constant: invalid constant tag '%c'\n", chr);
- return 1;
- }
-
- /* if we're filling in the last cdr field of a linked list, fix it up */
- if (lpage) {
- c_pop(&tm2_reg);
- put_ptr(CORRPAGE(tm2_reg.page), tm2_reg.disp + sizeof(POINTER),
- tmp_reg.page, tmp_reg.disp);
- c_pop(&tmp_reg); /* restore list header pointer */
- }
- return 0;
- }
-
- /************************************************************************/
- /* Read In a Hexadecimal Byte */
- /************************************************************************/
- unsigned char next_byte(void)
- {
- unsigned low, high;
-
- skip_space();
- high = (chr <= '9' ? chr - '0' : chr - 'A' + 10);
- sgetc();
- low = (chr <= '9' ? chr - '0' : chr - 'A' + 10);
-
- return (high << 4) | low;
- }
-
- /************************************************************************/
- /* Read In a Hexadecimal Word */
- /************************************************************************/
- unsigned next_word(void)
- {
- int highword = next_byte() << 8;
- return (highword | next_byte());
- }
-
- /************************************************************************/
- /* Read In a Floating Point Value */
- /************************************************************************/
- double next_flonum(void)
- {
- unsigned flo_parts[4]; /* "words" comprising a floating point value */
- int i;
-
- /* read in the four words comprising a floating point constant */
- for (i = 0; i < 4; i++)
- flo_parts[i] = next_word();
-
- /* convert "parts" of floating point value to a true floating point number */
-
- return (*((double *) flo_parts));
- }
-
- /************************************************************************/
- /* Read Character From Current Input File */
- /************************************************************************/
- char sgetc(void)
- {
- int stat;
-
- if (f_pos >= f_end) {
- file_end[file_no] = BUF_LENGTH;
- if ((stat = zread(file_handle[file_no], file_buffer[file_no],
- &file_end[file_no])) != 0) {
- zprintf("[VM INTERNAL ERROR] sfasl: read error status=%d\n", stat);
- }
- if ((f_pos = file_buffer[file_no]) >= (f_end = f_pos + file_end[file_no])) {
- return chr = EOF;
- }
- }
- return chr = *f_pos++;
- }
-
- /************************************************************************/
- /* Copy Block of Characters from Input Buffer to Scheme Block */
- /************************************************************************/
- void zap_chars(REGPTR ptr, unsigned offset, unsigned len)
- {
- int actual; /* the number of characters transfered in one move */
-
- while (len) {
- if (f_pos >= f_end) {
- sgetc();
- f_pos--;
- }
- actual = f_end - f_pos;
- if (len < actual)
- actual = len;
- toblock(ptr, offset, f_pos, actual);
- len -= actual;
- offset += actual;
- f_pos += actual;
- }
- }
-
- /************************************************************************/
- /* Reset Fasl Data Structures */
- /************************************************************************/
- void reset_fasl(void)
- {
- while (file_no >= 0) {
- zclose(file_handle[file_no]);
- free(file_buffer[file_no]);
- file_no--;
- }
- }